
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Random;


/**
 * 
 * @author yiwen zhong
 *
 */
public class Method {
	/**
	 * simulated annealing algorithm
	 * 
	 * @param s
	 * @return
	 */
	public static Solution SA(Solution s, int maxIteration, int sampleTimes, double alpha) {
		Solution current = new Solution(s);
		Solution best = new Solution(s);
        double t = 1000;
    	double[][] costs = new double[maxIteration/* * sampleTimes*/][2];
 		for (int q = 0; q < maxIteration; q++) {
			for (int k = 0; k < sampleTimes; k++) {
				Solution neighbor = current.neighbor();
				double p = Method.rand.nextDouble();
				double d = neighbor.getValue() - current.getValue();
				if ( d > 0 || p < 1.0/Math.exp(Math.abs(d)/t)) {
					//accept
					current = neighbor;
					if (current.getValue() > best.getValue()) {
						best.update(current);
						best.setLastImproving(q);
					} 
				}
			}
			costs[q][0] = current.getValue();
			costs[q][1] = best.getValue();
            t *= alpha;
		}
 		save(costs);
		return best;
	}

	   private static void save(double[][] costs) {
	    	if (!Simulation.SAVING_PROCESS_DATA) return;
	    	
	    	try {
	    		String fileName = "results/" + Problem.getFileName() + " alpha=" + Simulation.alpha + " convergence process.csv";
				System.out.println(fileName);
	    		PrintWriter printWriter = new PrintWriter(new FileWriter(fileName));
				for (int i = 0; i < costs.length; i++) {
					printWriter.print(costs[i][0]);
					for (int j = 1; j < costs[i].length; j++) {
						printWriter.print("," + costs[i][j]);
					}
					printWriter.println();
				}
				
				printWriter.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}	     	
	    }
	
	private static Random rand = new Random();
}
